/*****************************************************************************

*This software is developed within IEEE 1857.9 subgroup for the reference test model of Immersive Video Content Coding.
*Contributor: Yueming Wang, wymmail@foxmail.com, Peking University Shenzhen Graduate School

*****************************************************************************/
#define _USE_MATH_DEFINES
#include "stdafx.h"
#include <stdlib.h>
#include <math.h>
#include "global.h"
#include <string.h>

void calculation_psnr(sourceInfo *input, sourceInfo *output, configureInfo *cfi_in, configureInfo *cfi_out, float * psnr){
	long long diff_y = 0, diff_u = 0, diff_v = 0;

	//int width_uv = width >> 1;
	//int height_uv = height >> 1;

	int i, d;
	int size_y = input->width * input->height;
	int size_uv = size_y >> 2;

	for (i = 0; i < size_y; i++){
		d = input->buf_y[i] - output->buf_y[i];
		diff_y += d * d;
	}

	for (i = 0; i < size_uv; i++){
		d = input->buf_u[i] - output->buf_u[i];
		diff_u += d * d;
		d = input->buf_v[i] - output->buf_v[i];
		diff_v += d * d;
	}

	psnr[0] = (float)(10 * log10(65025.0f * size_y / diff_y));
	psnr[1] = (float)(10 * log10(65025.0f * size_uv / diff_u));
	psnr[2] = (float)(10 * log10(65025.0f * size_uv / diff_v));

}

#if MTK_ORIENTATION 
void sphere2cart(coordinate *sph, float *c){
	float lat = sph->latitude;
	float lon = sph->longitude;
  
	c[0] = sinf(lon) * cosf(lat);
	c[1] = sinf(lat);
	c[2] = cosf(lon) * cosf(lat);
}

void cart2sphere(float *c, coordinate *sph){
  float x, y, z;
  
	x = c[0]; y = c[1]; z = c[2];

	sph->latitude = asinf(y);
	sph->longitude = atan2f(x, z);
}
#endif
void calculation_spsnr(sourceInfo *input, sourceInfo *output, configureInfo *cfi_in, configureInfo *cfi_out, coordinate * sphere_point, int sphere_num, float * spsnr){
	int i;
	int src1_k, src2_k;
	float src1_i, src2_i;
	float src1_j, src2_j;
	double out_val, ref_val;
	double diff = 0, d;

	unsigned char * src[3][MAX_FACE];
	unsigned char * dst[3][MAX_FACE];
	coordinate sphere_in, sphere_out;

	handle_function.init_in_frame(input, cfi_in, src, 1);
	handle_function.init_out_frame(output, cfi_out, dst, 1);

	handle_function.pre_tread_in(input, cfi_in, src);
	handle_function.pre_tread_out(output, cfi_out, dst);

	for (i = 0; i < sphere_num; i++){

		sphere_in.latitude = sphere_out.latitude = (float)(sphere_point[i].latitude * M_PI / 180.0f);
		sphere_in.longitude = sphere_out.longitude = (float)(sphere_point[i].longitude * M_PI / 180.0f);
   
		handle_function.sphere_map_to_input(input, cfi_in, &src1_k, &src1_i, &src1_j, &sphere_in);
		handle_function.sphere_map_to_output(output, cfi_out, &src2_k, &src2_i, &src2_j, &sphere_out);

		src1_i -= SUBPIXEL;
		src1_j -= SUBPIXEL;
		src2_i -= SUBPIXEL;
		src2_j -= SUBPIXEL;

		out_val = handle_function.filter(src[0][src1_k], src1_i, src1_j, input->face_width[src1_k], input->face_height[src1_k], input->i_src);
		ref_val = handle_function.filter(dst[0][src2_k], src2_i, src2_j, output->face_width[src2_k], output->face_height[src2_k], output->i_src);

		d = out_val - ref_val;
		diff += d * d;
	}
	spsnr[0] = (float)(10 * log10(65025.0f * sphere_num / diff));
}

void init_function_psnr(sourceInfo *input_Info, sourceInfo *output_Info){
	handle_function.calculation_psnr = calculation_psnr;
	handle_function.calculation_spsnr = calculation_spsnr;
}